---
title: "JavaScript vs Python 语法对比"
description: "从 JavaScript 开发者视角深入对比两种语言的语法差异，快速掌握 Python 语法"
---

## 1. 引言

### 为什么需要语法对比？

作为 JavaScript 开发者，学习 Python 最大的挑战之一就是适应不同的语法风格。通过系统性的语法对比，我们可以：

- 快速理解 Python 的语法规则
- 避免常见的语法错误
- 建立两种语言之间的概念映射
- 提高学习效率

> 💡 **学习策略**：将 Python 语法视为 JavaScript 的"方言"，而不是完全陌生的语言

## 2. 基础语法对比

### 2.1 变量声明和赋值

<PythonEditor title="变量声明和赋值对比" compare={true} height={400}>
```javascript !! js
// 变量声明需要关键字
let name = "张三";
const age = 25;
var oldWay = "不推荐";

// 解构赋值
const [first, second] = [1, 2];
const { name: userName, age: userAge } = { name: "李四", age: 30 };

// 模板字符串
const message = `你好，${name}！你今年${age}岁。`;
console.log(message);
```

```python !! py
# 直接赋值，无需声明关键字
name = "张三"
age = 25

# 解构赋值（Python 3.6+）
first, second = 1, 2
user_info = {"name": "李四", "age": 30}
user_name, user_age = user_info["name"], user_info["age"] #模拟解构赋值（非自动解析）

# 更优雅的解构方式
user_info = {"name": "李四", "age": 30}
user_name, user_age = user_info.values()

# f-string（Python 3.6+）
message = f"你好，{name}！你今年{age}岁。"
print(message)
```
</PythonEditor>

**关键差异对比**

| 特性 | JavaScript | Python | 说明 |
|------|------------|--------|------|
| **声明方式** | `let/const/var` | 直接赋值 | Python 无需声明关键字 |
| **变量名** | camelCase | snake_case | Python 推荐下划线命名 |
| **常量** | `const` | 约定俗成（全大写） | Python 没有真正的常量 |
| **字符串格式化** | 模板字符串 | f-string | 两者都支持插值 |

### 2.2 数据类型对比

**基本数据类型**

<PythonEditor title="基本数据类型对比" compare={true}>
```javascript !! js
// JavaScript 基本类型
let string = "文本";
let number = 42;
let boolean = true;
let nullValue = null;
let undefinedValue = undefined;
let symbol = Symbol("unique");

// 引用类型
let array = [1, 2, 3];
let object = { key: "value" };
let functionName = () => {};

console.log(typeof string);
console.log(typeof number);
console.log(typeof boolean);
console.log(typeof nullValue);
console.log(typeof undefinedValue);
console.log(typeof symbol);
console.log(typeof array);
console.log(typeof object);
console.log(typeof functionName);
```

```python !! py
# Python 基本类型
string = "文本"
number = 42
boolean = True  # 注意大写
none_value = None  # 相当于 JavaScript 的 null
complex_number = 3 + 4j  # 复数类型

# 引用类型
array = [1, 2, 3]  # 列表（可变）
tuple_data = (1, 2, 3)  # 元组（不可变）
dictionary = {"key": "value"}  # 字典
set_data = {1, 2, 3}  # 集合

print(type(string))
print(type(number))
print(type(boolean))
print(type(none_value))
print(type(complex_number))
```
</PythonEditor>

**类型检查对比**

<PythonEditor title="类型检查对比" compare={true}>
```javascript !! js
// JavaScript 类型检查
console.log(typeof "hello");        // "string"
console.log(typeof 42);             // "number"
console.log(typeof true);           // "boolean"
console.log(typeof null);           // "object" (JavaScript 的著名 bug)
console.log(typeof undefined);      // "undefined"
console.log(Array.isArray([1,2,3])); // true
```

```python !! py
# Python 类型检查
print(type("hello"))        # <class 'str'>
print(type(42))             # <class 'int'>
print(type(True))           # <class 'bool'>
print(type(None))           # <class 'NoneType'>
print(isinstance([1,2,3], list))  # True
```
</PythonEditor>

### 2.3 作用域对比

作用域是编程中非常重要的概念，它决定了变量在代码中的可见性和生命周期。JavaScript 和 Python 在作用域处理上有一些重要差异。

#### 2.3.1 变量作用域

<PythonEditor title="作用域示例" compare={true}>
```javascript !! js
// 全局作用域
let globalVar = "我是全局变量";

function testScope() {
    // 函数作用域
    let functionVar = "我是函数内变量";
    
    if (true) {
        // 块级作用域（ES6+）
        let blockVar = "我是块级变量";
        console.log("块内访问:", blockVar);
        console.log("块内访问函数变量:", functionVar);
        console.log("块内访问全局变量:", globalVar);
    }
    
    // 块外无法访问块级变量
    // console.log(blockVar); // 错误！
    console.log("函数内访问函数变量:", functionVar);
    console.log("函数内访问全局变量:", globalVar);
}

testScope();
console.log("全局访问全局变量:", globalVar);
// console.log(functionVar); // 错误！
```

```python !! py
# 全局作用域
global_var = "我是全局变量"

def test_scope():
    # 函数作用域
    function_var = "我是函数内变量"
    
    if True:
        # Python 没有块级作用域！
        block_var = "我是块级变量"
        print("块内访问:", block_var)
        print("块内访问函数变量:", function_var)
        print("块内访问全局变量:", global_var)
    
    # 块外仍然可以访问块级变量
    print("函数内访问块级变量:", block_var)
    print("函数内访问函数变量:", function_var)
    print("函数内访问全局变量:", global_var)

test_scope()
print("全局访问全局变量:", global_var)
# print(function_var)  # 错误！
```
</PythonEditor>

#### 2.3.2 全局变量修改

<PythonEditor title="全局变量修改对比" compare={true}>
```javascript !! js
// JavaScript 全局变量修改
let counter = 0;

function increment() {
    counter++; // 直接修改全局变量
    console.log("计数器:", counter);
}

function incrementLocal() {
    let counter = 0; // 创建局部变量
    counter++;
    console.log("局部计数器:", counter);
}

increment();
increment();
incrementLocal();
console.log("全局计数器:", counter);
```

```python !! py
# Python 全局变量修改
counter = 0

def increment():
    global counter  # 声明使用全局变量
    counter += 1
    print("计数器:", counter)

def increment_local():
    counter = 0  # 创建局部变量
    counter += 1
    print("局部计数器:", counter)

increment()
increment()
increment_local()
print("全局计数器:", counter)
```
</PythonEditor>

#### 2.3.3 闭包对比

**JavaScript 闭包**

<PythonEditor title="闭包对比" compare={true}>
```javascript !! js
// JavaScript 闭包
function createCounter() {
    let count = 0;
    
    return {
        increment: function() {
            count++;
            return count;
        },
        getCount: function() {
            return count;
        }
    };
}

const counter1 = createCounter();
const counter2 = createCounter();

console.log(counter1.increment()); // 1
console.log(counter1.increment()); // 2
console.log(counter2.increment()); // 1
console.log(counter1.getCount());  // 2
console.log(counter2.getCount());  // 1
```

```python !! py
# Python 闭包
def create_counter():
    count = 0
    
    def increment():
        nonlocal count  # 声明使用外层变量
        count += 1
        return count
    
    def get_count():
        return count
    
    return {
        'increment': increment,
        'get_count': get_count
    }

counter1 = create_counter()
counter2 = create_counter()

print(counter1['increment']())  # 1
print(counter1['increment']())  # 2
print(counter2['increment']())  # 1
print(counter1['get_count']())  # 2
print(counter2['get_count']())  # 1
```
</PythonEditor>

**作用域关键差异总结**

| 特性 | JavaScript | Python | 说明 |
|------|------------|--------|------|
| **块级作用域** | ES6+ 支持 | 不支持 | Python 的 if/for 不创建新作用域 |
| **全局变量声明** | 直接修改 | 需要 `global` 关键字 | Python 更严格 |
| **闭包变量** | 自动捕获 | 需要 `nonlocal` 关键字 | Python 需要显式声明 |
| **变量提升** | 存在 | 不存在 | Python 更直观 |

扩展阅读：[Nonlocal vs global](https://chatgpt.com/s/t_6881a0c964508191b8c4a2c2218d3ba2)

### 2.4 控制流语句

#### 2.4.1 条件语句

<PythonEditor title="条件语句对比" compare={true}>
```javascript !! js
// if-else 语句
let age = 18;
if (age >= 18) {
    console.log("成年人");
} else if (age >= 12) {
    console.log("青少年");
} else {
    console.log("儿童");
}

// 三元运算符
let status = age >= 18 ? "成年人" : "未成年人";
console.log(status);

// switch 语句
let day = "Monday";
switch (day) {
    case "Monday":
        console.log("星期一");
        break;
    case "Tuesday":
        console.log("星期二");
        break;
    default:
        console.log("其他日子");
}
```

```python !! py
# if-elif-else 语句
age = 18
if age >= 18:
    print("成年人")
elif age >= 12:
    print("青少年")
else:
    print("儿童")

# 三元运算符（条件表达式）
status = "成年人" if age >= 18 else "未成年人" # 语法顺序为： 值 if 条件 else 否则的值
print(status)

# match 语句（Python 3.10+）
day = "Monday"
match day:
    case "Monday":
        print("星期一")
    case "Tuesday":
        print("星期二")
    case _:
        print("其他日子")
```
</PythonEditor>

#### 2.4.2 循环语句

<PythonEditor title="循环语句对比" compare={true}>
```javascript !! js
// for 循环
for (let i = 0; i < 5; i++) {
    console.log(i);
}

// for...of 循环（遍历可迭代对象）
const numbers = [1, 2, 3, 4, 5];
for (const num of numbers) {
    console.log(num);
}

// for...in 循环（遍历对象属性）
const person = { name: "张三", age: 25 };
for (const key in person) {
    console.log(`${key}: ${person[key]}`);
}

// while 循环
let count = 0;
while (count < 5) {
    console.log(count);
    count++;
}

// forEach 方法
numbers.forEach(num => console.log(num));
```

```python !! py
# for 循环（类似 JavaScript 的 for...of）
for i in range(5):
    print(i)

# 遍历列表
numbers = [1, 2, 3, 4, 5]
for num in numbers:
    print(num)

# 遍历字典
person = {"name": "张三", "age": 25}
for key, value in person.items():
    print(f"{key}: {value}")

# 只遍历键
for key in person:
    print(key)

# 只遍历值
for value in person.values():
    print(value)

# while 循环
count = 0
while count < 5:
    print(count)
    count += 1

# 列表推导式（Python 特色）
squares = [x**2 for x in range(5)]  # [0, 1, 4, 9, 16]
print(squares)
```
</PythonEditor>

## 3. 函数定义和调用

### 3.1 函数声明对比

<PythonEditor title="函数声明对比" compare={true}>
```javascript !! js
// 函数声明
function greet(name) {
    return `你好，${name}！`;
}

// 函数表达式
const greet2 = function(name) {
    return `你好，${name}！`;
};

// 箭头函数
const greet3 = (name) => {
    return `你好，${name}！`;
};

// 简写箭头函数
const greet4 = name => `你好，${name}！`;

// 默认参数
function greet5(name = "世界") {
    return `你好，${name}！`;
}

// 解构参数
function greet6({ name, age }) {
    return `你好，${name}！你今年${age}岁。`;
}

console.log(greet("张三"));
console.log(greet5());
console.log(greet6({ name: "李四", age: 25 }));
```

```python !! py
# 函数定义
def greet(name):
    return f"你好，{name}！"

# 默认参数
def greet2(name="世界"):
    return f"你好，{name}！"

# 类型注解（Python 3.5+）
def greet3(name: str) -> str:
    return f"你好，{name}！"

# 多参数
def greet4(name, age):
    return f"你好，{name}！你今年{age}岁。"

# 关键字参数
def greet5(name, age=None):
    if age:
        return f"你好，{name}！你今年{age}岁。"
    return f"你好，{name}！"

# 解构参数（使用字典）
def greet6(person):
    name = person["name"]
    age = person["age"]
    return f"你好，{name}！你今年{age}岁。"

print(greet("张三"))
print(greet2())
print(greet6({"name": "李四", "age": 25}))
```
</PythonEditor>

### 3.2 函数调用对比

<PythonEditor title="函数调用对比" compare={true}>
```javascript !! js
// 基本调用
function greet(name, age) {
    return `你好，${name}！你今年${age}岁。`;
}

console.log(greet("张三", 25));

// 解构调用
function greetPerson({ name, age }) {
    return `你好，${name}！你今年${age}岁。`;
}

console.log(greetPerson({ name: "李四", age: 25 }));

// 方法调用
const obj = {
    name: "王五",
    greet() {
        return `你好，${this.name}！`;
    }
};
console.log(obj.greet());
```

```python !! py
# 基本调用
def greet(name, age):
    return f"你好，{name}！你今年{age}岁。"

print(greet("张三", 25))

# 关键字参数调用
print(greet(name="李四", age=25))
print(greet(age=25, name="李四"))  # 参数顺序可以调换

# 字典解包
person = {"name": "王五", "age": 30}
print(greet(**person))

# 方法调用
class Person:
    def __init__(self, name):
        self.name = name
    
    def greet(self):
        return f"你好，{self.name}！"

person = Person("赵六")
print(person.greet())
```
</PythonEditor>

## 4. 数据结构对比

### 4.1 数组 vs 列表

<PythonEditor title="数组 vs 列表对比" compare={true}>
```javascript !! js
// 创建数组
const arr = [1, 2, 3, 4, 5];

// 添加元素
arr.push(6);           // 末尾添加
arr.unshift(0);        // 开头添加
arr.splice(2, 0, 2.5); // 中间插入

// 删除元素
arr.pop();             // 删除末尾
arr.shift();           // 删除开头
arr.splice(2, 1);      // 删除指定位置

// 查找元素
const index = arr.indexOf(3);
const found = arr.find(x => x > 3);

// 数组方法
const doubled = arr.map(x => x * 2);
const filtered = arr.filter(x => x > 2);
const sum = arr.reduce((acc, x) => acc + x, 0);

console.log("原数组:", arr);
console.log("翻倍:", doubled);
console.log("过滤:", filtered);
console.log("求和:", sum);
```

```python !! py
# 创建列表
arr = [1, 2, 3, 4, 5]

# 添加元素
arr.append(6)          # 末尾添加
arr.insert(0, 0)       # 开头添加
arr.insert(2, 2.5)     # 中间插入

# 删除元素
arr.pop()              # 删除末尾
arr.pop(0)             # 删除指定位置
del arr[2]             # 删除指定位置
arr.remove(3)          # 删除指定值
arr.insert(2, 3)       # 中间插入

# 查找元素
index = arr.index(3)   # 查找索引
found = next((x for x in arr if x > 3), None)

# 列表推导式
doubled = [x * 2 for x in arr]
filtered = [x for x in arr if x > 2]
sum_result = sum(arr)

print("原列表:", arr)
print("翻倍:", doubled)
print("过滤:", filtered)
print("求和:", sum_result)
```
</PythonEditor>

扩展阅读：[next 函数](https://docs.python.org/3/library/functions.html#next)

### 4.2 对象 vs 字典

<PythonEditor title="对象 vs 字典对比" compare={true}>
```javascript !! js
// 创建对象
const person = {
    name: "张三",
    age: 25,
    greet() {
        return `你好，${this.name}！`;
    }
};

// 访问属性
console.log(person.name);
console.log(person["name"]);

// 添加/修改属性
person.city = "北京";
person["job"] = "程序员";

// 删除属性
delete person.age;

// 遍历对象
for (const key in person) {
    console.log(`${key}: ${person[key]}`);
}

Object.keys(person).forEach(key => {
    console.log(`${key}: ${person[key]}`);
});

console.log(person.greet());
```

```python !! py
# 创建字典
person = {
    "name": "张三",
    "age": 25
}

# 访问属性
print(person["name"])
print(person.get("name"))  # 安全访问
print(person.get("city", "未知"))  # 默认值

# 添加/修改属性
person["city"] = "北京"
person["job"] = "程序员"

# 删除属性
del person["age"]
person.pop("age", None)  # 安全删除

# 遍历字典
for key, value in person.items():
    print(f"{key}: {value}")

for key in person.keys():
    print(f"{key}: {person[key]}")

for value in person.values():
    print(value)
```
</PythonEditor>

### 4.3 集合对比

<PythonEditor title="集合对比" compare={true}>
```javascript !! js
// 创建集合
const set = new Set([1, 2, 3, 3, 4]); // 自动去重

// 添加元素
set.add(5);

// 删除元素
set.delete(3);

// 检查元素
console.log(set.has(2));

// 集合操作
const set1 = new Set([1, 2, 3]);
const set2 = new Set([3, 4, 5]);

// 并集
const union = new Set([...set1, ...set2]);

// 交集
const intersection = new Set([...set1].filter(x => set2.has(x)));

// 差集
const difference = new Set([...set1].filter(x => !set2.has(x)));

console.log("并集:", Array.from(union));
console.log("交集:", Array.from(intersection));
console.log("差集:", Array.from(difference));
```

```python !! py
# 创建集合
set_data = {1, 2, 3, 3, 4}  # 自动去重

# 添加元素
set_data.add(5)

# 删除元素
set_data.remove(3)  # 如果不存在会报错
set_data.discard(3)  # 推荐使用，元素不存在时不会报错

# 检查元素
print(2 in set_data)

# 集合操作
set1 = {1, 2, 3}
set2 = {3, 4, 5}

# 并集
union = set1 | set2
union = set1.union(set2)

# 交集
intersection = set1 & set2
intersection = set1.intersection(set2)

# 差集
difference = set1 - set2
difference = set1.difference(set2)

print("并集:", union)
print("交集:", intersection)
print("差集:", difference)
```
</PythonEditor>

## 5. 错误处理对比

### 5.1 异常处理

<PythonEditor title="异常处理对比" compare={true}>
```javascript !! js
// 基本错误处理
try {
    const result = 10 / 0;
    console.log(result);
} catch (error) {
    console.error("发生错误:", error.message);
} finally {
    console.log("总是执行");
}

// 自定义错误
class CustomError extends Error {
    constructor(message) {
        super(message);
        this.name = "CustomError";
    }
}

// 抛出错误
function divide(a, b) {
    if (b === 0) {
        throw new CustomError("除数不能为零");
    }
    return a / b;
}

try {
    console.log(divide(10, 0));
} catch (error) {
    console.error("除法错误:", error.message);
}
```

```python !! py
# 基本错误处理
try:
    result = 10 / 0
    print(result)
except ZeroDivisionError as e:
    print(f"发生错误: {e}")
except Exception as e:
    print(f"其他错误: {e}")
else:
    print("没有异常时执行")
finally:
    print("总是执行")

# 自定义异常
class CustomError(Exception):
    def __init__(self, message):
        self.message = message
        super().__init__(self.message)

# 抛出异常
def divide(a, b):
    if b == 0:
        raise CustomError("除数不能为零")
    return a / b

try:
    print(divide(10, 0))
except CustomError as e:
    print(f"除法错误: {e.message}")
```
</PythonEditor>

## 6. 模块和导入对比

### 6.1 模块系统

<PythonEditor title="模块系统对比" compare={true} canRun={false}>
```javascript !! js
// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

export default class Calculator {
    constructor() {
        this.result = 0;
    }
    
    add(x) {
        this.result += x;
        return this;
    }
}

// main.js
import Calculator, { add, subtract } from './math.js';
import * as math from './math.js';

const calc = new Calculator();
console.log(add(5, 3));
console.log(math.subtract(10, 4));
```

```python !! py
# math_utils.py
def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

class Calculator:
    def __init__(self):
        self.result = 0
    
    def add(self, x):
        self.result += x
        return self

# main.py
from math_utils import add, subtract, Calculator
import math_utils as math

calc = Calculator()
print(add(5, 3))
print(math.subtract(10, 4))
```
</PythonEditor>

## 7. 练习题

### 练习 1：数据类型转换

将以下 JavaScript 代码转换为 Python：

<PythonEditor title="JavaScript 代码转换为 Python" compare={true}>
```javascript !! js
// JavaScript 版本
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2);
const evenNumbers = doubled.filter(x => x % 2 === 0);
const sum = evenNumbers.reduce((acc, x) => acc + x, 0);
console.log(sum);
```

```python !! py
# Python 版本
```
</PythonEditor>

<details>
<summary>查看答案</summary>

```python
# Python 版本
numbers = [1, 2, 3, 4, 5]
doubled = [x * 2 for x in numbers]
even_numbers = [x for x in doubled if x % 2 == 0]
sum_result = sum(even_numbers)
print(sum_result)
```

</details>

### 练习 2：函数定义

将以下 Python 函数转换为 JavaScript：

<PythonEditor title="Python 函数转换为 JavaScript" compare={true}>
```python !! py
# Python 版本
def process_data(data, callback=None):
    result = []
    for item in data:
        if callback:
            processed = callback(item)
        else:
            processed = item * 2
        result.append(processed)
    return result

# 使用示例
numbers = [1, 2, 3, 4, 5]
result = process_data(numbers, lambda x: x ** 2)
print(result)
```

```javascript !! js
// JavaScript 版本
```
</PythonEditor>


<details>
<summary>查看答案</summary>

```javascript
// JavaScript 版本
function processData(data, callback = null) {
    const result = [];
    for (const item of data) {
        let processed;
        if (callback) {
            processed = callback(item);
        } else {
            processed = item * 2;
        }
        result.push(processed);
    }
    return result;
}

// 使用示例
const numbers = [1, 2, 3, 4, 5];
const result = processData(numbers, x => x ** 2);
console.log(result);
```

</details>

### 练习 3：作用域理解

分析以下代码的输出结果：

<PythonEditor title="作用域练习" compare={true}>
```javascript !! js
// JavaScript 作用域练习
let x = 10;

function outer() {
    let x = 20;
    
    function inner() {
        let x = 30;
        console.log("inner x:", x);
    }
    
    inner();
    console.log("outer x:", x);
}

outer();
console.log("global x:", x);
```

```python !! py
# Python 作用域练习
x = 10

def outer():
    x = 20
    
    def inner():
        x = 30
        print("inner x:", x)
    
    inner()
    print("outer x:", x)

outer()
print("global x:", x)
```
</PythonEditor>

<details>
<summary>查看答案</summary>

**JavaScript 输出：**
```
inner x: 30
outer x: 20
global x: 10
```

**Python 输出：**
```
inner x: 30
outer x: 20
global x: 10
```

**解释：**
- 两个语言都遵循词法作用域规则
- 内层函数可以访问外层变量，但同名变量会创建新的局部变量
- 使用 `global`（Python）或直接修改（JavaScript）可以修改全局变量
</details>

## 8. 总结

### 关键差异总结

| 方面 | JavaScript | Python | 学习建议 |
|------|------------|--------|----------|
| **语法风格** | 大括号 + 分号 | 缩进敏感 | 注意 Python 的缩进规则 |
| **变量声明** | 需要关键字 | 直接赋值 | 适应 Python 的简洁性 |
| **命名规范** | camelCase | snake_case | 遵循 Python 的命名约定 |
| **字符串格式化** | 模板字符串 | f-string | 两者都很直观 |
| **循环语法** | for/while | for/while | Python 的 for 更简洁 |
| **函数定义** | function/箭头函数 | def | 语法差异较大 |
| **错误处理** | try-catch | try-except | 概念相似，语法不同 |
| **作用域** | 块级作用域 | 函数作用域 | 注意 Python 的全局变量声明 |

### 学习建议

1. **从相似点开始**：先学习两种语言相似的概念
2. **对比学习**：同时编写两种语言的代码
3. **实践为主**：多做练习题和项目
4. **注意细节**：关注语法细节的差异
5. **建立映射**：在心中建立两种语言的对应关系
6. **理解作用域**：深入理解变量作用域的概念和差异

### 下一步学习

在掌握了基础语法对比后，建议继续学习：

- 面向对象编程对比
- 异步编程模式
- 包管理和依赖管理
- 测试框架对比
- 实际项目开发

记住：语法只是工具，重要的是理解编程思想和解决问题的方法。Python 和 JavaScript 都是优秀的语言，各有特色，掌握两者会让你成为更全面的开发者。 